
/**
  ******************************************************************************
  * Copyright 2021 The Microbee Authors. All Rights Reserved.
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  * 
  * http://www.apache.org/licenses/LICENSE-2.0
  * 
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  * 
  * @file       sensor_airspeed_backend.h
  * @author     baiyang
  * @date       2023-8-1
  ******************************************************************************
  */

#pragma once

#ifdef __cplusplus
extern "C"{
#endif

/*----------------------------------include-----------------------------------*/
#include "sensor_airspeed_config.h"

#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>

#include <rtthread.h>
/*-----------------------------------macro------------------------------------*/

/*----------------------------------typedef-----------------------------------*/
enum airspeed_pitot_tube_order {
    AS_PITOT_TUBE_ORDER_POSITIVE = 0,
    AS_PITOT_TUBE_ORDER_NEGATIVE = 1,
    AS_PITOT_TUBE_ORDER_AUTO     = 2
};

enum AirspeedOptionsMask {
    AS_OM_ON_FAILURE_AHRS_WIND_MAX_DO_DISABLE                   = (1<<0),   // If set then use airspeed failure check
    AS_OM_ON_FAILURE_AHRS_WIND_MAX_RECOVERY_DO_REENABLE         = (1<<1),   // If set then automatically enable the airspeed sensor use when healthy again.
    AS_OM_DISABLE_VOLTAGE_CORRECTION                            = (1<<2),
    AS_OM_USE_EKF_CONSISTENCY                                   = (1<<3),
};

enum AirspeedDevType {
    AS_DEV_TYPE_SITL     = 0x01,
    AS_DEV_TYPE_MS4525   = 0x02,
    AS_DEV_TYPE_MS5525   = 0x03,
    AS_DEV_TYPE_DLVR     = 0x04,
    AS_DEV_TYPE_MSP      = 0x05,
    AS_DEV_TYPE_SDP3X    = 0x06,
    AS_DEV_TYPE_UAVCAN   = 0x07,
    AS_DEV_TYPE_ANALOG   = 0x08,
    AS_DEV_TYPE_NMEA     = 0x09,
    AS_DEV_TYPE_ASP5033  = 0x0A,
};

typedef struct sensor_as_backend *sensor_as_backend_t;
typedef const struct sensor_as_backend *sensor_as_backend_const_t;
typedef struct sensor_as_backend_ops *sensor_as_backend_ops_t;

struct sensor_as_backend {
    sensor_as_backend_ops_t ops;

    // mutex for access to shared frontend data
    rt_mutex_t _mutex;

    uint8_t instance;
};

struct sensor_as_backend_ops {
    void (*as_backend_destructor)(sensor_as_backend_t as_backend);
    bool (*init)(sensor_as_backend_t as_backend);
    bool (*get_differential_pressure)(sensor_as_backend_t as_backend, float *pressure);
    bool (*get_temperature)(sensor_as_backend_t as_backend, float *temperature);
    bool (*has_airspeed)(sensor_as_backend_t as_backend);
    bool (*get_airspeed)(sensor_as_backend_t as_backend, float *airspeed);
#if MB_AIRSPEED_HYGROMETER_ENABLE
    bool (*get_hygrometer)(sensor_as_backend_t as_backend, uint32_t *last_sample_ms, float *temperature, float *humidity);
#endif
};

/*----------------------------------variable----------------------------------*/

/*-------------------------------------os-------------------------------------*/

/*----------------------------------function----------------------------------*/
void sensor_as_backend_ctor(sensor_as_backend_t as_backend, sensor_as_backend_ops_t _ops, char *name, uint8_t _instance);
int8_t sensor_as_backend_get_pin(sensor_as_backend_const_t as_backend);
float sensor_as_backend_get_psi_range(sensor_as_backend_const_t as_backend);
uint8_t sensor_as_backend_get_bus(sensor_as_backend_const_t as_backend);
bool sensor_as_backend_bus_is_confgured(sensor_as_backend_const_t as_backend);
void sensor_as_backend_set_bus_id(sensor_as_backend_t as_backend, uint32_t id);
bool sensor_as_backend_disable_voltage_correction();
enum airspeed_pitot_tube_order sensor_as_backend_get_tube_order(sensor_as_backend_const_t as_backend);
float sensor_as_backend_get_airspeed_ratio(sensor_as_backend_const_t as_backend);
void sensor_as_backend_set_use_zero_offset(sensor_as_backend_t as_backend);
void sensor_as_backend_set_skip_cal(sensor_as_backend_t as_backend);
void sensor_as_backend_set_offset(sensor_as_backend_t as_backend, float ofs);
void sensor_as_backend_set_use(sensor_as_backend_t as_backend, int8_t use);

/// 
void as_backend_destructor(sensor_as_backend_t as_backend);

static inline void sensor_as_backend_destructor(sensor_as_backend_t as_backend) {
    if (as_backend->ops->as_backend_destructor != NULL) {
        as_backend->ops->as_backend_destructor(as_backend);
        return;
    }

    as_backend_destructor(as_backend);
}

static inline bool sensor_as_backend_init(sensor_as_backend_t as_backend) {
    RT_ASSERT(as_backend->ops->init != NULL);

    return as_backend->ops->init(as_backend);
}

static inline bool sensor_as_backend_get_differential_pressure(sensor_as_backend_t as_backend, float *pressure) {
    if (as_backend->ops->get_differential_pressure != NULL) {
        return as_backend->ops->get_differential_pressure(as_backend, pressure);
    }

    return false;
}

static inline bool sensor_as_backend_get_temperature(sensor_as_backend_t as_backend, float *temperature) {
    RT_ASSERT(as_backend->ops->get_temperature != NULL);

    return as_backend->ops->get_temperature(as_backend, temperature);
}

static inline bool sensor_as_backend_has_airspeed(sensor_as_backend_t as_backend) {
    if (as_backend->ops->has_airspeed != NULL) {
        return as_backend->ops->has_airspeed(as_backend);
    }

    return false;
}

static inline bool sensor_as_backend_get_airspeed(sensor_as_backend_t as_backend, float *airspeed) {
    if (as_backend->ops->get_airspeed != NULL) {
        return as_backend->ops->get_airspeed(as_backend, airspeed);
    }

    return false;
}

#if MB_AIRSPEED_HYGROMETER_ENABLE
// optional hygrometer support
static inline bool sensor_as_backend_get_hygrometer(sensor_as_backend_t as_backend, uint32_t *last_sample_ms, float *temperature, float *humidity) {
    if (as_backend->ops->get_hygrometer != NULL) {
        return as_backend->ops->get_hygrometer(as_backend, last_sample_ms, temperature, humidity);
    }

    return false;
}
#endif

static inline uint8_t sensor_as_backend_get_instance(sensor_as_backend_t as_backend) {
    return as_backend->instance;
}

/*------------------------------------test------------------------------------*/

#ifdef __cplusplus
}
#endif



